tree grammar VariableWrapper;

options 
{
	tokenVocab=LPMEDLexer; // use the vocabulary from the parser
	ASTLabelType=CommonTree; // what kind of trees are we walking?
	language = CSharp2;
	output = AST;
}

@namespace { Core.ANTLRGrammars }

@header
{
using System.Collections.Generic;
}
@members
{
	IList<string> WatchNames;
}

program[IList<string> watchnames]
scope
{
 string DDname;
}
@init
{
	WatchNames = watchnames;
}
	:
		^(CPROGRAM ^(CDEVICE name=ID) {$program::DDname=$name.text;} block)
	;


block 	: (varDecList)* blockStmt;


varDecList : varDecListAtom+ ;


varDecListAtom :  ^(CTYPE TYPE peremDecList);


peremDecList : ID+;


blockStmt : ^(CSTATEMENT stmt*)
;


stmt
options { backtrack=true;}
:			assign 
		|	ifStmt
		|	^(CWHILE expr blockStmt)
		|	^(CFOR assign expr assign blockStmt)
		|	deviceFuncID
		|	blockStmt
		|	^(CBREAKPOINT INT)
		|	CTERMINATEALL
		|	functionCall
;

assign options{backtrack=true;}	
:	
	^(CASSIGN ID expr)
		-> {WatchNames.Contains($ID.text)}? ^(CREGMETHACCESS ID[$ID.text + ":SetValue"]  expr)
		-> ^(CASSIGN ID expr)
;

ifStmt
options { backtrack=true; }
: 
	^(CIFTE expr blockStmt blockStmt?)
;

expr options{backtrack=true;}
:	
			^(OpOr expr expr )
		|	^(OpAnd expr expr )
		|	^(OpLogicalB expr expr )
		|	^(OpLogicalA expr expr )
		|	^(OpAddSub expr expr )
		|	^(OpDivMul expr expr )
		|	^(OpNegation expr )
		|	^(OpUnar expr )
		|	'(' expr ')'
		|	atom
;

atom
options
{
	backtrack=true;
}	
 :
 ID	-> {WatchNames.Contains($ID.text)}? ^(CREGFUNCACCESS ID[$ID.text + ":GetValue"])
	-> ID
 | ^(CFLOAT FLOAT)
 | ^(CINT INT)
 | ^(CBOOL DBOOL)
 | ^(OBJECTNAME ID) ^(NODES ID*) ^(MEMBERNAME ID)
 | ^(CGETSTATE ^(OBJECTNAME ID) ^(NODES ID*))
;

qualifiedName	:
	^(OBJECTNAME ID) ^(NODES ID*) ^(MEMBERNAME ID)
;

deviceFuncID 	
:       
        	^(CCALL ^(CSYNCCALL qualifiedName))			
	|	^(CCALL ^(CASYNCCALL qualifiedName))
	|	^(CCALL ^(CENDTHECALL qualifiedName))
	|	^(CCALL ^(CWAITTHECALL qualifiedName))
	|	^(CCALL ^(CWAITANYCALL qualifiedName))
;


functionCall
: 
			^(CASYNCFUNCCALL ID parameter*)
		| 	^(CWAITFUNCFINISH ID parameter*)
		|	^(CSYNCFUNCCALL ID parameter*)
;


parameter	: 
	^(PARAM parameterValue)
;

parameterValue	:
			ID		//variable
		| 	INT		//number
		|	qualifiedName	//named state
;